Skip to content

feat(security): implement nonce-based CSP to remove unsafe-inline and unsafe-eval from current policy#4424

Open
bogdanmariusc10 wants to merge 5 commits intomainfrom
4330-icacf-26-securitypen-testingreview-and-tighten-the-content-security-policy-directives
Open

feat(security): implement nonce-based CSP to remove unsafe-inline and unsafe-eval from current policy#4424
bogdanmariusc10 wants to merge 5 commits intomainfrom
4330-icacf-26-securitypen-testingreview-and-tighten-the-content-security-policy-directives

Conversation

@bogdanmariusc10
Copy link
Copy Markdown
Collaborator

@bogdanmariusc10 bogdanmariusc10 commented Apr 24, 2026

🔗 Related Issue

Closes #4330
Jira Issue: https://jsw.ibm.com/browse/ICACF-26


📝 Summary

This PR implements a comprehensive Content Security Policy (CSP) solution that removes unsafe-inline and unsafe-eval directives, addressing security vulnerabilities identified in the pentesting report.

What changed:

  • Removed unsafe-inline from script-src directive (prevents XSS attacks)
  • Removed unsafe-eval entirely from CSP (blocks dynamic code execution)
  • Implemented cryptographically secure nonce-based CSP using secrets.token_urlsafe(16) (128 bits of entropy per request)
  • Added 'unsafe-hashes' to script-src for inline event handlers (onclick, onload, etc.)
  • Configured HTMX 2.0.3 to use CSP nonces via htmx.config.inlineScriptNonce
  • Kept 'unsafe-inline' for style-src only (required for Alpine.js dynamic inline styles)

Why this matters:

  • Prevents XSS attacks - Only scripts with matching nonces can execute, blocking malicious inline script injection
  • Blocks dynamic code execution - eval(), Function constructor, and similar dangerous functions are now blocked
  • Follows OWASP best practices - Modern nonce-based CSP is the recommended approach for securing web applications
  • HTMX 2.0.3 compatibility - No longer uses eval(), making it CSP-compliant

🏷️ Type of Change

  • Feature / Enhancement
  • Bug fix
  • Documentation
  • Refactor
  • Chore (deps, CI, tooling)
  • Other (describe below)

🧪 Verification

Check Command Status
Formatting make black isort autoflake ✅ PASS
Linting make ruff ✅ PASS
Admin UI Manual testing ✅ PASS

✅ Checklist

  • Code formatted (make black isort pre-commit)
  • Tests added/updated for changes
  • Documentation updated (if applicable)
  • No secrets or credentials committed

📓 Notes

Security Impact

Before:

Content-Security-Policy: script-src 'self' 'unsafe-inline' 'unsafe-eval' ...
  • ❌ Any inline script could execute (XSS vulnerability)
  • ❌ eval() and similar functions allowed (code injection risk)

After:

Content-Security-Policy: script-src 'self' 'nonce-ABC123...' 'unsafe-hashes' https://cdnjs.cloudflare.com ...
                         style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com ...
  • ✅ Only scripts with matching nonce can execute
  • ✅ eval() and similar functions blocked
  • ✅ Unique nonce per request (128 bits of entropy)
  • ✅ Inline event handlers allowed via 'unsafe-hashes'
  • ✅ Alpine.js dynamic styles work via style-src 'unsafe-inline'

Implementation Details

Core CSP Implementation (mcpgateway/middleware/security_headers.py:295-311):

  • Generates cryptographically secure nonce per request using secrets.token_urlsafe(16)
  • Stores nonce in request.state.csp_nonce for template access
  • Configures CSP directives with nonce-based script-src
  • Separates style-src to allow 'unsafe-inline' (Alpine.js requirement)

HTMX Configuration (mcpgateway/templates/admin.html:321-327):

  • Sets window.htmxConfig.inlineScriptNonce before HTMX bundle loads
  • Allows HTMX inline event handlers (hx-on:*) to work with strict CSP

HTMX Nonce Application (mcpgateway/admin_ui/admin.js:15-19):

  • Reads nonce from window.htmxConfig and applies to htmx.config.inlineScriptNonce
  • Ensures all HTMX-generated inline scripts include the nonce

Files Modified:

  • mcpgateway/middleware/security_headers.py - Core CSP with nonce generation
  • mcpgateway/templates/admin.html - HTMX nonce configuration
  • mcpgateway/admin_ui/admin.js - Applied nonce to htmx.config
  • .secrets.baseline - Updated baseline

Technical Notes

HTMX 2.0.3 Compatibility:

  • HTMX 2.0 removed eval() usage, making it CSP-compliant
  • Inline event handlers (hx-on:*) require either nonces or 'unsafe-hashes'
  • We use both: nonces for explicit scripts, 'unsafe-hashes' for inline handlers

Alpine.js Requirement:

  • Alpine.js generates dynamic inline styles at runtime
  • Requires 'unsafe-inline' in style-src (cannot use nonces for styles)
  • This is an acceptable security trade-off for UI framework functionality

Security Trade-offs:

  • 'unsafe-hashes' allows inline event handlers (onclick, etc.) - acceptable for trusted admin UI
  • 'unsafe-inline' for styles only - lower risk than scripts
  • No 'unsafe-eval' - highest priority security improvement

PenTest Findings Addressed

unsafe-inline removed from script-src - Replaced with nonce-based whitelisting
unsafe-eval removed entirely - No dynamic code execution allowed
Modern CSP implementation - Follows OWASP best practices

…e-eval

- Remove 'unsafe-inline' and 'unsafe-eval' from Content-Security-Policy
- Implement cryptographically secure nonce generation per request (secrets.token_urlsafe(16))
- Add csp_nonce Jinja2 global function for template access
- Update 19 inline scripts across 13 templates with nonce attributes
- Fix CSP consistency test to validate structure instead of exact match
- Add type annotations to new helper functions

Addresses pen testing findings:
- Prevents XSS attacks via inline script injection
- Blocks dynamic code execution (eval, Function constructor)
- Follows OWASP CSP best practices

Files modified:
- mcpgateway/middleware/security_headers.py (CSP implementation)
- mcpgateway/main.py (Jinja2 global registration)
- mcpgateway/version.py (fallback template support)
- tests/security/test_security_headers.py (updated CSP test)
- 13 HTML templates (added nonce attributes)

All tests passing, code formatted and linted.

Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
@bogdanmariusc10 bogdanmariusc10 added enhancement New feature or request security Improves security SHOULD P2: Important but not vital; high-value items that are not crucial for the immediate release pentesting labels Apr 24, 2026
Bogdan-Marius-Catanus added 4 commits April 24, 2026 12:32
Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
- Remove unsafe-inline from script-src (prevents XSS attacks)
- Remove unsafe-eval entirely (blocks dynamic code execution)
- Implement cryptographically secure nonce generation (128-bit entropy)
- Configure HTMX 2.0.3 with htmx.config.inlineScriptNonce
- Add 'unsafe-hashes' to script-src for inline event handlers
- Keep 'unsafe-inline' for style-src only (Alpine.js requirement)

Addresses pentesting report findings on CSP misconfiguration.

Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
Signed-off-by: Bogdan-Marius-Catanus <bogdan-marius.catanus@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request pentesting security Improves security SHOULD P2: Important but not vital; high-value items that are not crucial for the immediate release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ICACF-26] [Security][Pen Testing]Review and tighten the Content Security Policy directives

1 participant